package xmlschema;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


interface XMLList<E>{
    public List<E> getList();
}

/*
 * class for PEOPLE_XML's root
*/
@XmlRootElement(name = "People")
class Listings implements XMLList<Person> {
    /*
     * node people only contains people list
    */
    @XmlElement(name = "Person")
    private ArrayList<Person> Person;

    /*
     * people list
    */
    @Override
    public List<Person> getList() {
        return Person;
    }
}

public class DataUtilities {
    /*
     * xml file name for Products object
    */
    private final static String PEOPLE_XML  = "MainTest.xml";

    /*
     * Lazy initiate static inner class for 
    */
    private static class UtilitiesHolder {    
        static DataUtilities instance = new DataUtilities();    
    }

    //private constructor is needed for singleton
    private DataUtilities(){}

    //products
    private List<Person> PersonList;

    /*
     * Lazy initial to get product list
    */
    public List<Person> getPersonList() {
        if (PersonList == null) {
            createLists();
        }
        return PersonList;
    }

    /*
     * convert xml files to java objects
    */
    private void createLists() { 
        PersonList = xmlToObject(Listings.class, PEOPLE_XML);
    }
    
    /*
     * Convert a xml file to instance of class by given file name
     * @param clazz  to be converted java object's class
     * @param file   xml file name
     * @return a list of object that xml's root contains
    */
    private <U, V extends XMLList<U>> List<U> xmlToObject(Class<V> clazz, 
            String file) {
        try {
            JAXBContext context = JAXBContext.newInstance(clazz);
            Unmarshaller um = context.createUnmarshaller();
            @SuppressWarnings("unchecked")
            V cs = (V) um.unmarshal(new File(file));
            return cs.getList();
        } catch (JAXBException ex) {
            throw new RuntimeException(ex);
        }   
    }

    /*
     * static factory method for singleton
    */
    public static DataUtilities getUtilities(){
        return UtilitiesHolder.instance;
    }
}
